/**
 * ReportGear(2011)
 */
package net.abbp.report.model;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * 单元格网格，统一管理模型中的单元格
 * 
 * @version 1.0 2011-3-11
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since Report 1.0
 */
class CellGrid {
    // Cell列表
    CellList cells = new CellList();

    /**
     * 总行数
     */
    private int rowCount = 5;
    /**
     * 总列数
     */
    private int columnCount = 5;

    /**
     * 添加单元格
     * 
     * @param cell 单元格
     */
    public void add(Cell cell) {
        this.rowCount = Math.max(this.rowCount, cell.getRow() + cell.getRowSpan());
        this.columnCount = Math.max(this.columnCount, cell.getColumn() + cell.getColumnSpan());

        this.cells.add(cell);
    }

    /**
     * 移除单元格
     * 
     * @param cell 单元格
     */
    public void remove(Cell cell) {
        if (!this.cells.remove(cell)) {
            // 移除单元格出错!
        }
    }

    /**
     * 获取指定单元格
     * 
     * @param column
     *            列 0 based
     * @param row
     *            行 0 based
     * @return 单元格
     */
    public Cell getCell(int column, int row) {
        for (Cell c : this.cells) {
            if ((c.getColumn() == column) && (c.getRow() == row)) {
                return c;
            }
        }

        return Cell.EMPTY_CELL;
    }

    /**
     * 设置指定单元格的值
     * 
     * @param column
     *            列 0 based
     * @param row
     *            行 0 based
     * @param value
     *            值
     */
    public void setCellValue(int column, int row, Object value) {
        Cell cell = this.getCell(column, row);

        if (cell == Cell.EMPTY_CELL) {
            cell = new Cell(column, row);

            this.add(cell);
        }

        cell.setValue(value);
    }

    /**
     * 清除Cell的值
     * 
     * @param column
     *            行 0 based
     * @param row
     *            列 0 based
     */
    public void clearCell(int column, int row) {
        this.getCell(column, row).clear();
    }

    /**
     * @return 单元格迭代器
     */
    public Iterator<Cell> cellIterator() {
        return new CellIterator();
    }

    /**
     * Cell交叉集
     * 
     * @param columnFrom
     *            开始行 0 based
     * @param rowFrom
     *            开始列 0 based
     * @param columnSpan
     *            列跨度
     * @param rowSpan
     *            行跨度
     * @return 迭代器
     */
    public Iterator<Cell> intersect(int columnFrom, int rowFrom, int columnSpan, int rowSpan) {
        return new IntersectIterator(columnFrom, rowFrom, columnSpan, rowSpan);
    }

    /**
     * CellGrid列迭代器
     * 
     * @param column
     *            列 0 based
     * @return 列迭代器
     */
    public Iterator<Cell> getColumn(int column) {
        return new ColumnIterator(column);
    }

    /**
     * CellGrid行迭代器
     * 
     * @param row
     *            行 0 based
     * @return 行迭代器
     */
    public Iterator<Cell> getRow(int row) {
        return new RowIterator(row);
    }

    /**
     * 获取包含指定类型对象的单元格迭代器
     * 
     * @param clazz
     *            元素类
     * @return 迭代器
     */
    public Iterator<Cell> getCellsByElementClass(Class<?> clazz) {
        return new CellElementIterator(clazz);
    }

    /**
     * 增加行
     * 
     * @param index
     *            索引
     */
    void addRow(int index) {
        // 所有行大于等于index的行加 1
        for (Cell c : this.cells) {
            if (c.getRow() >= index) {
                c.setRow(c.getRow() + 1);
            }
        }

        this.rowCount++;
    }

    /**
     * 增加列
     * 
     * @param index
     *            索引
     */
    void addColumn(int index) {
        // 所有列大于等于index的列加 1
        for (Cell c : this.cells) {
            if (c.getColumn() >= index) {
                c.setColumn(c.getColumn() + 1);
            }
        }

        this.columnCount++;
    }

    /**
     * 删除指定行
     * 
     * @param index
     *            索引
     */
    void deleteRow(int index) {
        // 删除此行元素
        // 所有行大于index的行-1
        for (int size = this.cells.size() - 1, i = size; i >= 0; i--) {
            Cell c = this.cells.get(i);
            if (c.getRow() > index) {
                c.setRow(c.getRow() - 1);
            } else if (c.getRow() == index) {
                this.cells.remove(c);
            } else {
                break;
            }
        }

        this.rowCount--;
    }

    /**
     * 删除指定列
     * 
     * @param index
     *            索引
     */
    void deleteColumn(int index) {
        // 删除此列元素
        // 所有列大于index的列-1
        for (int size = this.cells.size() - 1, i = size; i >= 0; i--) {
            Cell c = this.cells.get(i);
            if (c.getColumn() > index) {
                c.setColumn(c.getColumn() - 1);
            } else if (c.getColumn() == index) {
                this.cells.remove(c);
            }
        }

        this.columnCount--;
    }

    @Override
    public CellGrid clone() {
        //TODO 改写
        CellGrid cloned = new CellGrid();
        cloned.rowCount = this.rowCount;
        cloned.columnCount = this.columnCount;
        
        cloned.cells = new CellList();
        for (Cell r : this.cells) {
            cloned.cells.add(r.clone());
        }

        return cloned;
    }

    /**
     * 获取总行数
     * 
     * @return 总行数
     */
    public int getRowCount() {
        return rowCount;
    }

    /**
     * 获取总列数
     * 
     * @return 总列数
     */
    public int getColumnCount() {
        return columnCount;
    }

    /**
     * 列迭代器
     * 
     */
    private class ColumnIterator implements Iterator<Cell> {

        private int columnIndex;
        private int ptr = 0;
        private Cell next;

        ColumnIterator(int columnIndex) {
            this.columnIndex = columnIndex;
            findNext();
        }

        public boolean hasNext() {
            return (this.next != null);
        }

        public Cell next() {
            if (!hasNext()) {
                throw new NoSuchElementException("已到最后一个元素");
            }
            Cell cell = this.next;
            findNext();

            return cell;
        }

        public void remove() {
            throw new UnsupportedOperationException("不支持");
        }

        private void findNext() {
            Cell c;
            do {
                if (ptr >= cells.size()) {
                    this.next = null;
                    return;
                }

                c = cells.get(ptr++);
            } while (c.getColumn() != this.columnIndex);

            this.next = c;
        }
    }

    /**
     * 行迭代器
     */
    private class RowIterator implements Iterator<Cell> {

        private int rowIndex;
        private int ptr = 0;
        private Cell next;

        public RowIterator(int rowIndex) {
            this.rowIndex = rowIndex;
            findNext();
        }

        public boolean hasNext() {
            return (this.next != null);
        }

        public Cell next() {
            if (!(hasNext())) {
                throw new NoSuchElementException("已到最后一个元素");
            }
            Cell cell = this.next;

            findNext();

            return cell;
        }

        public void remove() {
            throw new UnsupportedOperationException("不支持");
        }

        private void findNext() {
            Cell c;
            do {
                if (ptr >= cells.size()) {
                    this.next = null;
                    return;
                }

                c = cells.get(ptr++);
            } while (c.getRow() != this.rowIndex);

            this.next = c;
        }
    }

    /**
     * 单元格迭代器
     */
    private class CellIterator implements Iterator<Cell> {
        private int ptr = 0;
        private Cell next;

        CellIterator() {
            findNext();
        }

        public boolean hasNext() {
            return (this.next != null);
        }

        public Cell next() {
            if (!hasNext()) {
                throw new NoSuchElementException("已到最后一个元素");
            }
            Cell cell = this.next;

            findNext();
            return cell;
        }

        public void remove() {
            throw new UnsupportedOperationException("不支持");
        }

        private void findNext() {
            if (ptr >= cells.size()) {
                this.next = null;
                return;
            }

            this.next = cells.get(ptr++);
        }
    }

    /**
     * 交叉单元迭代器
     */
    private class IntersectIterator implements Iterator<Cell> {

        private int columnFrom;
        private int columnTo;
        private int rowFrom;
        private int rowTo;
        private int ptr = 0;
        private Cell next;

        IntersectIterator(int columnFrom, int rowFrom, int columnTo, int rowTo) {
            this.next = null;
            this.columnFrom = Math.max(columnFrom, 0);
            this.columnTo = Math.min(columnFrom + columnTo - 1, getColumnCount() - 1);
            this.rowFrom = Math.max(rowFrom, 0);
            this.rowTo = Math.min(rowFrom + rowTo - 1, getRowCount() - 1);

            findNext();
        }

        public boolean hasNext() {
            return (this.next != null);
        }

        public Cell next() {
            if (!(hasNext())) {
                throw new NoSuchElementException("已到最后一个元素");
            }
            Cell cell = this.next;

            findNext();
            return cell;
        }

        public void remove() {
            throw new UnsupportedOperationException("不支持");
        }

        private void findNext() {
            Cell c;

            for (;;) {
                if (ptr >= cells.size()) {
                    this.next = null;
                    return;
                }

                c = cells.get(ptr++);
                if ((c.getRow() >= this.rowFrom) && (c.getColumn() >= this.columnFrom) && (c.getRow() <= this.rowTo)
                        && (c.getColumn() <= this.columnTo)) {
                    this.next = c;

                    return;
                }
            }
        }
    }

    /**
     * 单元格值为制定对象的单元格迭代器
     */
    private class CellElementIterator implements Iterator<Cell> {
        private int ptr = 0;
        private Cell next = null;
        private Class<?> valueClass;

        CellElementIterator(Class<?> valueClass) {
            this.valueClass = valueClass;
            findNext();
        }

        public boolean hasNext() {
            return (this.next != null);
        }

        public Cell next() {
            if (!(hasNext())) {
                throw new NoSuchElementException("已到最后一个元素");
            }
            Cell cell = this.next;

            findNext();
            return cell;
        }

        public void remove() {
            throw new UnsupportedOperationException("不支持");
        }

        private void findNext() {
            for (;;) {
                if (ptr >= cells.size()) {
                    this.next = null;
                    return;
                }

                Cell c = cells.get(ptr++);
                if (this.valueClass.isInstance(c.getValue())) {
                    this.next = c;
                    break;
                }
            }
        }
    }
}
